package com.hlm.testredis.util;


import java.util.*;

/**
 * @program:test-redis
 * @description:分布工具包
 * @author: xinY
 * @create:2020-07-25 11:01
 **/
public class DistributeUtil {
    /**
     * 概率密度函数曲线
     * @param metas
     * @return Map
     */
    public static Map<Double,Double> distribute(double[] metas){
        Double variance = info(metas).get("variance");
        Double avg = info(metas).get("average");
        // count
        Map<Double,Integer> map = new HashMap<>();
        for(int i = 0 ; i < metas.length ; i ++) {
            Integer count = map.get(metas[i]);
            map.put(metas[i], count == null ? 1 : count + 1);
//            System.out.println(metas[i] + "有"+map.get(metas[i])+"个");
        }

        Map<Double,Double> resultMap = new HashMap<>();
//        概率密度函数---------------------------------------------------------------
        for(int i = 0 ; i < metas.length ; i ++){
            double left = 1.0/Math.sqrt(2 * Math.PI * variance);
            double right = Math.exp(-((metas[i]-avg) * (metas[i]-avg)/(2 * variance)));
            double midu = left * right ;
//            System.out.println("x:"+ metas[i] + "y:" + midu);

            resultMap.put(metas[i],midu);
        }
        return resultMap;
    }

    /**
     * 分组分布
     * @param metas 数据源
     * @param interval 组间距
     * @param groupNum  组数
     */
    public static Map<Double,Integer> group(double[] metas,double interval , int groupNum){
        Double avg = info(metas).get("average");
        Double metaMax = info(metas).get("max");
        Double metaMin = info(metas).get("min");
        Double variance = info(metas).get("variance");

//        System.out.println("最大值："+metaMax+"最小值："+metaMin+"平均值："+avg+"方差："+variance);

        // count
        Map<Double,Integer> map = new HashMap<>();
        for (double meta : metas) {
            Integer count = map.get(meta);
            map.put(meta, count == null ? 1 : count + 1);
        }
        // 分布下线
        double downLimitGroup;
        downLimitGroup = avg - interval * Math.sqrt(variance);
        // 分布上限
        double upLimitGroup = avg + interval * Math.sqrt(variance);
        // 组距
        double groupInterval = (upLimitGroup - downLimitGroup)/(groupNum -1);

        Map<Double,Integer> resultMap = new HashMap<>();
        int countPerGroup = 0;
        double y = 0;
        double gaiLvMidu = 0;
        for(int i = 0 ; i < metas.length ; i ++){
            if(metas[i] <= downLimitGroup && downLimitGroup <= upLimitGroup){
                int count = map.get(metas[i]);
                countPerGroup = countPerGroup + count;
                double gailv = map.get(metas[i]) * 1.0/metas.length;
                y = y +gailv;

            }else{
                gaiLvMidu = y/groupInterval;
//                System.out.println("x:"+ downLimitGroup + "y:" + y + "gaiLvMidu:" + gaiLvMidu);
                if(countPerGroup!= 0 ){
                    resultMap.put(downLimitGroup,countPerGroup);
                }
                y = 0;
                gaiLvMidu = 0 ;
                countPerGroup = 0;
                downLimitGroup = downLimitGroup + groupInterval ;
            }
        }
        /*for(Double key : resultMap.keySet()){
            System.out.println("key:"+key+"value:"+resultMap.get(key));
        }*/
        return resultMap;
    }

    public static Map<String,Double> info(double[] metas){
        Map<String,Double> resultMap = new HashMap<>();
        Arrays.sort(metas);
        // 最大值最小值
        double metaMin = metas[0];
        double metaMax = metas[metas.length-1];
        System.out.println("源数据有" + metas.length + "个");

        //平均数
        double sum = 0 ;
        for(int i = 0 ; i < metas.length ; i ++){
            sum = sum + metas[i];
        }
        double avg = sum/metas.length;

        //方差
        double sumCha = 0 ;
        for(int i = 0 ; i < metas.length ; i ++){
            double cha = metas[i]-avg;
            sumCha = sumCha + (cha * cha);
        }
        double variance = sumCha/metas.length;
//        System.out.println("最大值："+metaMax+"最小值："+metaMin+"平均值："+avg+"方差："+variance);

        resultMap.put("min",metaMin);
        resultMap.put("max",metaMax);
        resultMap.put("average",avg);
        resultMap.put("variance",variance);
        resultMap.put("max",metaMax);
        resultMap.put("min",metaMin);
        for(String key : resultMap.keySet()){
            System.out.println(key + "=========" + resultMap.get(key));
        }
        return resultMap;
    }

    public static Map<String,Double> infoGroup(double[] metas ,double interval,Integer groupNum){
        Map<String,Double> resultMap = new HashMap<>();

        Map<String,Double> metaMap = info(metas);
        Double avg = metaMap.get("average");
        Double variance = metaMap.get("variance");

        // count
        Map<Double,Integer> map = new HashMap<>();
        for(int i = 0 ; i < metas.length ; i ++) {
            Integer count = map.get(metas[i]);
            map.put(metas[i], count == null ? 1 : count + 1);
        }
        // 分布下线
        double downLimitGroup = avg - interval * Math.sqrt(variance);
        // 分布上限
        double upLimitGroup = avg + interval * Math.sqrt(variance);
        // 组距
        double groupInterval = (upLimitGroup - downLimitGroup)/(groupNum -1);

        resultMap.put("average",avg);
        resultMap.put("variance",variance);
        resultMap.put("downLimitGroup",downLimitGroup);
        resultMap.put("upLimitGroup",upLimitGroup);
        resultMap.put("groupInterval",groupInterval);

        /*for(String key : resultMap.keySet()){
            System.out.println("key:"+key + "||value:" + resultMap.get(key));
        }*/
        return resultMap;
    }


    public static Map<Double,Integer> countPerGroup(double[] metas ,double interval , Integer groupNum){
        Map<Double,Integer> resultMap = new HashMap<>();
        Arrays.sort(metas);
        Double variance = info(metas).get("variance");
        Double avg = info(metas).get("average");
        // 分布下线
        double downLimitGroup = avg - interval * Math.sqrt(variance);
        // 分布上限
        double upLimitGroup = avg + interval * Math.sqrt(variance);
        // 组距
        double groupInterval = (upLimitGroup - downLimitGroup)/(groupNum -1);
        int countPerGroup = 0 ;
        for(int i = 0 ; i < metas.length ; i ++){
            System.out.println("循环第"+i+"次");
            System.out.println("metas[i]是："+metas[i]+"，downlimitgroup是："+downLimitGroup+"，uplimitgroup是："+upLimitGroup);
            if(metas[i] <= downLimitGroup && downLimitGroup <= upLimitGroup){
                countPerGroup = countPerGroup +1 ;
                System.out.println("此时metas[i]<= down 并且 down<=up;;;groupcount="+countPerGroup);
            }else{
                System.out.println("x:"+downLimitGroup + "====y:"+countPerGroup);
                resultMap.put(downLimitGroup,countPerGroup);
                downLimitGroup = downLimitGroup + groupInterval;
                // 此时 有一个在夹缝中的数据，把他加进去
                countPerGroup =    1;
                // 最后的一个组里面没有东西  （有14个组，应该有15个组）
                System.out.println("count 是"+countPerGroup+"  ，，， down是"+downLimitGroup);
            }
            System.out.println("循环第"+i+"次结束");
        }

        return  resultMap;
    }
}
